home *** CD-ROM | disk | FTP | other *** search
/ MACD 5 / MACD 5.bin / workbench / docs / asm_guide / assembler course / doctext3-assembler < prev    next >
Text File  |  1980-12-25  |  16KB  |  437 lines

  1.  
  2.                 By now you will probably know how
  3.     to start a verticalblanking interrupt. Here's how to do it.
  4.  
  5.         In $6c.L is the address where the computer will jump to 
  6.     each time the Vblank occurs. If you want to put your own routine
  7.     (like a replay routine) in the Vblank interrupt, you just take the
  8.     address in $6c, and save it somewhere (to jump back to when your 
  9.     routine is ready) and put the startaddress of your own routine in it.
  10.  
  11. ..        ...
  12.         MOVE.L    $6C,OLDINT+2        ; SAVE JUMP-BACK ADDRESS
  13.         MOVE.L    #INT,$6C        ; OUR OWN ROUTINE
  14.         ...
  15.  
  16.  
  17.     INT:    ....
  18.         ....
  19.     OLDINT:    JMP    $00000000        ; OLDINT= 'JMP'-OPCODE
  20.                         ; OLDINT+2 = JUMPBACK ADDR.
  21.  
  22.         There are addresses for all interrupts (like $6c). On the
  23.     '!' page I sent last time are other addresses too. Now I have only
  24.     used the Vblank and the Keyboardinterrupt. (this is $68) It occurs
  25.     when you press a key AND when you release it again. Interpreting 
  26.     a pressed key is somewhat difficult. The code for the pressed key
  27.     is found in $bfec01, but first you got to do some operations on it.
  28.     Here's the routine:
  29.  
  30. ..    KEYINT:    CLR.L    D0
  31.         MOVE.B    $BFEC01,D0
  32.         NOT.B    D0
  33.         ROR.B    #1,D0            ; bit 8 is up/donw code
  34.     1)    ANDI.W    #$007F,D0        ; NOW, D0 = RAW KEYCODE
  35.         ....
  36.     OLDKEYINT:
  37.         JMP    $0000000        ; install as vblankint
  38.  
  39.     The code you get in D0 after these operations is what is called
  40.     the RAW keycode. It's NOT an ascii value or something. Somewhere
  41.     in the pack you'll find a table with these codes. As you'll see,
  42.     ALL keys have a value, even the SHIFT and CTRL-keys.
  43.     The line with '1)' kills the leftmost bit in D0.B, this bit is 0 if
  44.     the key is currently PRESSED and 1 if it is RELEASED. To get the
  45.     code in the table you have to compare only the other bits, so in line
  46.     1) this bit is killed. To know if the key is pressed or released, you
  47.     have to check bit 8 before this line. It could be important to check
  48.     because when you perform a printroutine each time you get a keyboard
  49.     interrupt, you will get each pressed key 2 times on the screen (once
  50.     when you press, once when you release)
  51.     
  52.  
  53.     LIBRARIES
  54.     ---------
  55.  
  56.     Now let's talk a bit about libraries and library-routines. You sure
  57.     have heard that there are several interesting (and less interesting)
  58.     routines stored in the libraries. Most important libraries are in
  59.     ROM, others are on disk (in the libraries directory)  To use routs
  60.     of a lib, you must first open this library, in other words, you must
  61.     get to know where the library is in memory (relative addressing, 
  62.     remember ?)  If the lib is not in memory, it will be loaded from disk
  63.     when you open it. There is a routine which is called 'OPENLIB', and
  64.     it gives you the starting address of the library you opened. Other
  65.     routines are located at a fixed place, relative to this starting
  66.     address. You got some lists of the (standard) libraries from AmigaDos
  67.     There are other libraries, like Explode Library, but they are not
  68.     'offcial' libraries, and I don't have lists of the routines in them.
  69.     If you want, you can create your own libraries, but you'll have to
  70.     find out yourself. Maybe you can learn me when you did. Anyway, let's
  71.     go on. Most routines have some parameters. If you know something 
  72.     about C-language, it could be very simple to understand:
  73.  
  74.       result = function([parameter][...])
  75.  
  76.     General rule: only 1 result ! In Machinecode, this result is Always
  77.     stored in register D0.  The parameters differ from routine to rout.
  78.     See lists in previous sending. For example: the routine OPEN in 
  79.     the dos-library.  you'll find:
  80.  
  81.         -$001e  -30   Open (name, accessmode)(d1,d2)
  82.  
  83.     Which means, routine OPEN is at ofset -$001e (or -30 decimal) in the
  84.     doslib, and parameters are NAME in D1, and accessmode in D2. The
  85.     result is in D0. 
  86.     As said, opening a library in fact means getting the startaddress.
  87.     When you know that the function 'Openlib' is in a library itself,
  88.     you could ask the question : how would you open THIS library ?
  89.      GOOD QUESTION !  The answer is: You Don't Have to !! The startaddr
  90.     of this library is known, you can find it in $4.  (MOVE.L $4,A6
  91.     will put the startaddress of the exec.library in A6, remember: it's
  92.     the CONTENTS of $4 and not $4 that is the startaddress !)
  93.     Once you got this address, you can call any routine in this library,
  94.     among which is OpenLib, so now you can open the other libraries, like
  95.     for example the doslib.
  96.     Here's a complete source of how to open the Dos-library:
  97.  
  98. ..    opendoslib:
  99.         move.l    $4.w,a6            ; load execbase
  100.         lea.l    dosname,a1        ; parameter for openlib
  101.         jsr    -408(a6)        ; execute routine openlib
  102.         move.l    d0,dosbase        ; store result
  103.         tst.l    d0            ; something wrong ?
  104.         beq    error            ; yep !
  105.         rts                ; nope !
  106.  
  107.     error:    ....                ; HELP, something wrong !
  108.  
  109.     dosname:    dc.b    "dos.library",0
  110.             even
  111.     dosbase:    dc.l    0
  112.  
  113.     As said, D0 is the result of the operation. In most cases, if D0 is
  114.     zero (tst.l d0), there was something wrong, like the library couldn't
  115.     be opened, etc.  However, when you can't open Doslib, not much can be
  116.     done I'm afraid, and it won't happen anyway, so you don't have to
  117.     check this really. But when you open a dozen of windows, it could 
  118.     happen that you run out of memory, and a D0=0 would tell you so.
  119.     After your source is ready to RTS to CLI, you should always close
  120.     opened libraries (except the EXEC, which in fact you didn't open)
  121.     This is done as follows:
  122.  
  123. ..    Closedoslib:
  124.         move.l    $4.w,a6            ; load execbase
  125.         move.l    dosbase,a1        ; start of lib to close
  126.         jsr    -414(a6)        ; close it
  127.  
  128.     2 notes on this:  move.l dosbase,a1     IS NOT THE SAME AS 
  129.               lea.l  dosbase,a1  !!!
  130.     You really need the VALUE IN dosbase and not the address #dosbase.
  131.     (I say this coz I made this mistake often)
  132.     2nd note:  MOVE.L  $4.W,a6    notice the $4.W : this saves you 2
  133.     bytes: address $4 is in the lowest 64K of memory, and so it can be
  134.     addressed using only 1 word instead of 1 longword. 
  135.     move.l    $4,a6   is assembled something like this:  3245 00000004
  136.     move.l  $4.w,a6     "    "    "    :  3265 0004
  137.     WOW AIN'T THAT SHOCKING !! WE SAVED 2 BYTES !!
  138.     (and we wasted only 7 lines)
  139.  
  140.     Now here's some detailed descriptions of the parameters for the 
  141.     most commonly used DOSLIB routines, I can't tell'em all, 1) coz I
  142.     haven't used them yet and I dunno, 2) coz there are too much of'em
  143.     3) coz I haven't got all day 4) coz you won't be using them neither.
  144.  
  145.     One very interesting routine is the EXECUTE. It makes it possible to
  146.     run any file on disk (like a demo) straight from an assembler program
  147.     (like a MENU or a LOADER...) Here's the routine, (ofcourse after
  148.     opening the DOSLIB)
  149.  
  150.  
  151. ..    EXECUTE_IT:
  152.         ...
  153.         move.l    dosbase,a6        ; load dosbase
  154.         move.l    #command,d1        ; pointer to command in d1
  155.         clr.l    d2
  156.         clr.l    d3
  157.         jsr    -222(a6)        ; execute
  158.         move.l    d0,returncode        ; optional, not often used
  159.         ...
  160.  
  161.     command:    dc.b    "df0:demo1",0    ; filename to execute
  162.             even
  163.  
  164.     d2 and d3 are used to redirect input and output (just set to zero
  165.     if you don't use them)  (like  "dir df0: > dirfile",  d2 would be
  166.     a pointer to "DIRFILE")
  167.     When you wish to use 'execute' routine, the command RUN should be in
  168.     the C: directory. If RUN isn't there, nothing will be executed...
  169.     The result of the excute is a returncode, which the finished program
  170.     gives back in d0. (You sometimes see badly written demos giving a
  171.     returncode = xxxxx  when they're finished, so now you know why: they
  172.     forgot to clear D0 at the end. (This is only noticable when they're
  173.     run from within a batchfile))  In advanced DOS-scripts, this is used
  174.     to give results (like 'file not found') to other doscommands.
  175.  
  176. ..    OPEN_FILE:
  177.         ...
  178.         move.l    dosbase,a6        ; load dosbase
  179.         move.l    #filename,d1        ; ptr to filename
  180.         move.l    #1005,d2        ; mode = read
  181.         jsr    -30(a6)            ; open
  182.         move.l    d0,handle        ; save result
  183.         ...
  184.  
  185.     filename:    dc.b    "df0:boringfile",0
  186.             even
  187.     handle:        dc.l    0
  188.  
  189.     You can open a file in 3 ways:  read from it: mode = 1005
  190.     write to it: mode = 1006, and read/write: mode = 1004
  191.     in D0 you get the handle to that file, you need it for further 
  192.     operations.
  193.  
  194. ..    READING A FILE
  195.  
  196.     the description for this routine is:
  197.  
  198.     amount = Read (handle, buffer, length)
  199.       d0   =  -42    d1      d2      d3
  200.  
  201.     (This is a somewhat shorter notation, I'll use this in the next 
  202.     examples. One last time, I'll give you the source for this)
  203.  
  204.         ...
  205.         move.l    dosbase,a6
  206.         move.l    handle,d1        ; d1 = handle (value)
  207.         move.l    #buffer,d2        ; d2 = buffer (pointer to)
  208.         move.l    #length,d3        ; d3 = length (value)
  209.         jsr    -42(a6)            ; Read
  210.         move.l    d0,....            ; optional
  211.  
  212.     handle:        dc.l    0        ; filled by 'lock'
  213.     length=        xxxxx
  214.     buffer:        blk.b    length,0
  215.             even
  216.  
  217.     You can read more than one time, in fact you can read until you
  218.     reach the end of the file.
  219.     d0 is the amount of bytes read (amount <= length)
  220.     d0 = 0 :  end of file reached
  221.     d0 = -1 : error (disk removed or something, I suppose)
  222.  
  223. ..    WRITING A FILE
  224.  
  225.     amount = Write (handle, buffer, length)
  226.      d0       -48    d1       d2      d3
  227.  
  228.     same param's as in read
  229.  
  230. ..    SEEK
  231.  
  232.     move the file-pointer in a opened file
  233.  
  234.     Position = SEEK (handle, distance, mode)
  235.        d0       -66    d1       d2      d3
  236.  
  237.     mode tells whether the distance is measured starting at the start
  238.     of the file (mode = -1), or from the current position (mode = 0)
  239.     or starting at the end (mode = 1)
  240.     Distance then tells the offset from the defined position:
  241.     Distance -20 with mode 1 puts the filepointer to 20 bytes from the
  242.     end of the file etc.
  243.  
  244. ..    IOERR
  245.  
  246.     get the precise dos-error
  247.  
  248.     error = IOERR ()
  249.      d0       -132
  250.  
  251.     Refer to DOS-manual for errorvalues & meanings: example
  252.  
  253.         121: not executable ('file is not an object module')
  254.         221: disk full
  255.         ...
  256.  
  257.  
  258.     OK, so much for the most important dos-routines.  Maybe you'll use
  259.     some of these in a menu or a bootloader or something.
  260.     As I know out of experience, it's best not to mess around with the
  261.     interrupts/DMA when using DOS routines, coz there's much chance that
  262.     it won't work/crash once in a while. 
  263.     The Readdir routine which is desacribed now, is causing me LOADS of
  264.     trouble, it just won't work when I want it, and the weird thig is that
  265.     it works sometimes. I HATE THAT ! I have to cancel all my current
  266.     projects coz they all need these silly diskactivities and they just
  267.     don't work together with my hardware-routines. (I told you before)
  268.  
  269.  
  270.         ....
  271.         move.l    dosbase(pc),a6
  272.         move.l    #path,d1        ; name of directory
  273.         moveq.l    #-2,d2            ; read
  274.         jsr    -84(a6)            ; 'lock'
  275.         tst.l    d0
  276.         beq.s    dir_error
  277.         move.l    d0,lock
  278.  
  279.         move.l    lock(pc),d1
  280.         move.l    #fileinfo,d2        ; ptr to fileinfo block
  281.         jsr    -102(a6)        ; 'examine'
  282.         tst.l    d0            ;    fills up fileinfo with
  283.         beq.s    dir_error        ;    info about the directory 
  284.     
  285.     dir_loop:
  286.         move.l    lock(pc),d1
  287.         move.l    #fileinfo,d2
  288.         jsr    -108(a6)        ; 'examine next'
  289.         tst.l    d0            ;    fills up fileinfo with
  290.         beq    dir_error        ;    info about files/subdirs
  291.         bsr    dir_printnames        ; routine to print name
  292.         bra.s    dir_loop        ; next, until d0 = 0
  293.     dir_error:
  294.         jsr    -132(a6)        ; IOERR check which error
  295.         rts
  296.     
  297.     path:        dc.b    "df0:",0
  298.             even
  299.     lock:        dc.l    0
  300.     fileinfo:    blk.b    260,0
  301.  
  302.  
  303.     The routines 'examine' and 'exnext' will fill up a block of data
  304.     (fileinfo) which has the following structure:
  305.  
  306.     offset:    0    drivenumber
  307.         4    type of entry (dir/file)
  308.         8    filename (108 bytes)
  309.         116    protection code
  310.         120    type of entry
  311.         124    size of file (bytes)
  312.         128    number of blocks
  313.         132    days    \
  314.         136    minutes     |  creation time
  315.         140    ticks    /
  316.         144    comment (116 bytes filenote)
  317.         260
  318.  
  319.     As I said, I've still got major problems with this thing, and I
  320.     haven't been able to test all of it. For example I think that the
  321.     name of a directory starts at ofset 10 instead of ofset 8, but I'm
  322.     not sure. This book I got isn't complete by a 100 lightyears !
  323.     Above all, in the whole book are several 'typing errors' as it is
  324.     translated from German. Ow boy.
  325.  
  326.     Anyway, now we've seen nearly all of the DOS-things, it's time to
  327.     go to a lower level: the TRACKDISK device. Devices are something
  328.     between hardware and library-programming. There are several devices,
  329.     like 'trackdisk', 'printer', 'console',...
  330.     They use more 'sophisticated' stuff like nodes and messages to 
  331.     communicate between other tasks, and it's this stuff that I'm trying
  332.     to master now (but it's not working yet) Anyway, I've done some
  333.     experiments with trackdisk already. here's an attempt:
  334.  
  335.     doio:    move.l    $4.w,a6            ;
  336.         sub.l    a1,a1            ; 
  337.         jsr    -294(a6)        ; findtask (buerk)
  338.         move.l    d0,readreply+$10    ; 
  339.         lea.l    readreply,a1        ; 
  340.         jsr    -354(a6)        ; addport (buerk)
  341.         lea.l    diskio,a1        ;
  342.          move.l    #0,d0            ; drive:  df0:
  343.         clr.l    d1            ; no flags (?)
  344.         lea.l    devicename,a0        ;
  345.         jsr    -444(a6)        ; opendevice !!
  346.         tst.l    d0
  347.         bne.s    trerror
  348.  
  349.         lea.l    diskio,a1
  350.         move.l    #readreply,14(a1)    ; reply port (buerk)
  351.         move.w    #2,28(a1)        ; instruction : read
  352.         move.l    #diskbuff,40(a1)    ; ptr to buffer
  353.         move.l    #.....,36(a1)        ; amount of bytes to read
  354.         move.l    #.....,44(a1)        ; ofset on disk
  355.         jsr    -456(a6)        ; do-I/O
  356.     
  357.         lea.l    diskio,a1
  358.         move.w    #9,28(a1)
  359.         move.l    #0,36(a1)
  360.         jsr    -456(a6)        ;motorout
  361.         lea.l    readreply,a1
  362.         jsr    -360(a6)        ;remport (buerk)
  363.         lea.l    diskio,a1
  364.         jsr    -450(a6)        ;closedev
  365.     trerror:rts
  366.     
  367.     diskio:        blk.l    20,0
  368.     readreply:    blk.l    8,0
  369.     devicename:    dc.b    "trackdisk.device",0
  370.             even
  371.     diskerror:    dc.b    0
  372.             even
  373.     diskbuff:    dc.l    0
  374.  
  375.  
  376.     The routines with 'Buerk' are not really clear to me. They refer to
  377.     a structure that is used by the device, it looks like this:
  378.  
  379.     ofset:    0    ...        ; typical node structure,
  380.                     ; don't bother
  381.         14    pointer to replyport (task communication)
  382.         18    length of structure (don't bother)
  383.  
  384.         20    pointer to devicenode (don't bother)
  385.         24    unit (don't bother) (?)
  386.         28    command:  These are (some of) the possible commands
  387.             for the devices:
  388.                 read:        #2
  389.                 write:        #3
  390.                 update:        #4 (?)
  391.                 clear:        #5 (?)
  392.                 motorout:    #9 (only for trackdisk)
  393.         30    flags (don't bother) (?)
  394.         31    error (example: 28 = write prot)
  395.              (didn't work when I tried or I did smth wrong)
  396.         32    actual number of read/written bytes
  397.         36    number of bytes to send/recieve
  398.             example:    number = 2*512:  2 blocks to transfer
  399.         40    ptr to memory
  400.         44    offset (amount of bytes behind 1st byte on disk)
  401.             example: offset = 880*512:  read/write at block 880
  402.                  there are 22 blocks/track
  403.  
  404.     Maybe it's now the right time to tell you the relation between the
  405.     different 'levels' of ROM-routines in the AMiga. At the highest
  406.     level you have the DOS-routines, like read, write, execute. As you
  407.     can imagine, there's a whole lot of programming behind these commands
  408.     as they handle trackread, updating of directory, detecting of errors
  409.     directory/file handling, checksums, free space etc.  The next level 
  410.     is the TRACKDISK. Dos-routines use the trackdisk-device, this is not
  411.     as sophisticated as DOS, as it only reads/writes tracks, there's 
  412.     nothing like file/directory/checksums at this level. It's therefor a
  413.     whole bit faster. (especially coz you can reduce the read/write-head
  414.     movement to a minimum by putting programs on consecutive tracks.
  415.     Most megademos use trackdisk, you can recognise it by a 'tack-tack-
  416.     tack' with constant speed. The lowest level is the DMA, like we did
  417.     when using blitter, for example. You can just as well put values in
  418.     special registers used for diskdrive, and get some things read 
  419.     from disk. This is the most complicated way of working, and also 
  420.     the fastest.Working this way you can chenge the speed of the drive-
  421.     head (and make the funny noise you sometimes with some hardware 
  422.     loader (njiiii-njiiii-retetetete / ow boy it's melting !!)
  423.     I've heard that you can kill your drive by messing too much with the
  424.     drive-hardware registers, but anyway, sounds fascinating. You can also
  425.     read tracks behind 79 with the hardware-method, which could make head
  426.     trying to read on the plastic of your disks. (aaargh)
  427.     These same 3 levels can be found in other parts of the amiga, but 
  428.     coz of a lack of decent documentation, I haven't been able to 
  429.     experiment on them. Until then we will go on messing with the
  430.     hardware and the DMA.
  431.  
  432.  
  433.     NOW. I guess you know most thing you need to know now, for more
  434.     detailled things you can now refer to manual, (most manuals forget
  435.     that there are beginners too in this world, they just are too 
  436.     difficult to start with)
  437.